#include "EDBaseAfx.h"
#include "EventEx.h"
#include "TaskFunT.h"


///SlotDispatchTask----------------------------------------------------------------------------------
SlotDispatchTask::SlotDispatchTask(const GPSlot& slot,const EventSender& sender,const Bundle& bundle,IEventSlot* pSlot)
: m_slot(slot)
, m_sender(sender)
, m_bundle(bundle)
, m_pEventSlot(NULL)
{
	m_pEventSlot = pSlot;
}

SlotDispatchTask::~SlotDispatchTask()
{
	m_pEventSlot.Release();
}

void SlotDispatchTask::Run()
{
	if (m_pEventSlot && m_pEventSlot->Connected()) 
	{
		if (m_slot)
		{
			m_slot(m_sender, m_bundle);
		}
	}
}

///EventHandlerUISlot---------------------------------------------------------------------------------------------
EventHandlerUISlot::EventHandlerUISlot(const GPSlot& slot,EventSetEx *pOwner) : EventSlot(slot),m_pOwner(pOwner)
{
	DMASSERT(m_pOwner);
}

bool EventHandlerUISlot::Invoke(EventSender& sender, Bundle& args)
{
	SlotDispatchTask* _pSlotDispatchTask = new SlotDispatchTask(GetSlot(), sender, args, this);
	bool bRet = m_pOwner->DispatchUiEvent(_pSlotDispatchTask);
	if (!bRet)
	{
		_pSlotDispatchTask->Release();
	}
	return bRet;
}

EventSlot* EventHandlerUISlot::Clone() const
{
	return new EventHandlerUISlot(this->GetSlot(),m_pOwner);
}

///EventHandlerUIWnd---------------------------------------------------------------------------------------------
EventHandlerUIWnd::EventHandlerUIWnd(DWORD dwThreadId): m_MsgId(WM_USER + 1767), m_dwThreadId(dwThreadId)
{
}

void EventHandlerUIWnd::DispatchUiEvent(SlotDispatchTask* _pSlotDispatchTask)
{
	if (NULL != _pSlotDispatchTask)
	{
		if (m_hWnd != NULL)
		{
			this->PostMessage(m_MsgId, (WPARAM)_pSlotDispatchTask, 0);
		}
		else
		{
			_pSlotDispatchTask->Release();
		}
	}
}

EventHandlerUIWnd* EventHandlerUIWnd::New(DWORD dwThreadId)
{
	EventHandlerUIWnd* obj = new EventHandlerUIWnd(dwThreadId);
	if (obj)
	{
		ATOM Atom = g_pDMApp->GetClassAtom();
		if (obj->DMCWnd::CreateWindowEx((LPCWSTR)Atom,NULL,0,0,0,0,1,1,HWND_MESSAGE,0))
		{
			return obj;
		}
		else 
		{
			obj->m_dwThreadId = 0;
		}
	}
	return NULL;
}

void EventHandlerUIWnd::Del(EventHandlerUIWnd*& refObj)
{
	if (refObj)
	{
		if (refObj->IsWindow())
		{
			refObj->DestroyWindow();
		}
		delete refObj;
	}
}

LRESULT EventHandlerUIWnd::OnHandlerEvent(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	SlotDispatchTask* _dispathObject =  reinterpret_cast<SlotDispatchTask*>(wParam);
	if (_dispathObject)
	{
		_dispathObject->Run();
		_dispathObject->Release();
	}
	return S_OK;
}

EventHandlerWorkerSlot::EventHandlerWorkerSlot(const GPSlot& slot,EventSetEx *pOwner) : EventSlot(slot),m_pOwner(pOwner)
{
	DMASSERT(m_pOwner);
}

bool EventHandlerWorkerSlot::Invoke(EventSender& sender, Bundle& args)
{
	return m_pOwner->DispatchAsyncEvent(GetSlot(), sender, args);
}

EventSlot* EventHandlerWorkerSlot::Clone() const
{
	return new EventHandlerWorkerSlot(this->GetSlot(),m_pOwner);
}

///GlobalEventSet---------------------------------------------------------------------------------------------
EventSetEx::EventSetEx()
: m_bRunTaskThread(false)
, m_uiThreadHandler(NULL)
, m_bRunUiHandler(false)
, m_dwUiThreadId(0)
{
}

EventSetEx::~EventSetEx()
{
	if (m_bRunTaskThread)
	{
		m_TaskSvc.StopTaskSvc();
		m_bRunTaskThread = false;
	}

	//
	EventHandlerUIWnd::Del(m_uiThreadHandler);
	m_bRunUiHandler = false;
}

bool EventSetEx::InitEvent(DWORD dwThreadId)
{
	if (0 != dwThreadId && GetUiThreadHandlerImpl(dwThreadId))
	{
		m_dwUiThreadId = dwThreadId;
		return true;
	} 
	else
	{
		return false;
	}
}

Event::Connection EventSetEx::ConnectUiEvent(const std::string& eventName, const GPSlot& slot, Event::Group group /*= -1*/)
{
	DMSmartPtrT<EventHandlerUISlot> pdispatchUIEvent;pdispatchUIEvent.Attach(new EventHandlerUISlot(slot,this));
	RefEvent EventObj = GetEventObject(eventName, true);
	return EventObj->ConnectSlot(*pdispatchUIEvent, group);
}

Event::Connection EventSetEx::ConnectAsyncEvent(const std::string& eventName, const GPSlot& slot, Event::Group group /*= -1*/)
{
	DMSmartPtrT<EventHandlerWorkerSlot> pdispatchWorkerEvent;pdispatchWorkerEvent.Attach(new EventHandlerWorkerSlot(slot,this));
	return GetEventObject(eventName, true)->ConnectSlot(*pdispatchWorkerEvent, group);
}

bool EventSetEx::DispatchUiEvent(SlotDispatchTask* _pSlotDispatchTask)
{
	EventHandlerUIWnd* uiThreadHandlerImpl = GetUiThreadHandlerImpl(m_dwUiThreadId);
	if (uiThreadHandlerImpl) 
	{
		uiThreadHandlerImpl->DispatchUiEvent(_pSlotDispatchTask);
		return true;
	}
	return false;
}

EventHandlerUIWnd* EventSetEx::GetUiThreadHandlerImpl(UINT uiThreadHandler)
{
	if (0 == uiThreadHandler) return NULL;
	if (NULL == m_uiThreadHandler && false == m_bRunUiHandler)
	{
		m_uiThreadHandler	= EventHandlerUIWnd::New(uiThreadHandler);
		m_bRunUiHandler		= true;
	}
	return m_uiThreadHandler;
}

bool EventSetEx::DispatchAsyncEvent(const GPSlot& slot, const EventSender& sender, const Bundle& evt)
{
	bool bSuccess = false;
	if (false == m_bRunTaskThread) 
	{
		m_TaskSvc.InitTaskSvc();
		m_bRunTaskThread = m_TaskSvc.RunTaskSvc();
	}

	if (m_bRunTaskThread)
	{
		bSuccess = m_TaskSvc.AddTask(NewRunnableFunction(&EventSetEx::DispatchEvent, slot, sender, evt), true);
	}

	return bSuccess;
}

bool EventSetEx::DispatchEvent(const GPSlot& slot, const EventSender& sender, const Bundle& evt)
{
	return slot(sender, evt);
}


